<?php

class RedpackAction extends CommonAction
{

    private static $instance;
    const host = '127.0.0.1';
    const port = '6379';
    const timeout = 300;
   // const auth = 'redis2018';
    const auth = '';
    const shuqian_key = 'shuqian_redpack_list';

    public static function getRedisInstance()
    {
        if (self::$instance) {
            return self::$instance;
        }
        try {
            $redis = new \Redis();
            $con = $redis->connect(self::host, self::port, self::timeout);

            if (false == $con) {
                throw new \Exception('connect redis fail');
            }
            if (self::auth) {
                $success = $redis->auth(self::auth);
                if (false == $success) {
                    throw new \Exception('redis auth fail');
                }
            }
            $sel = $redis->select(0);
            if (false == $sel) {
                throw new \Exception('select db fail');
            }
            return self::$instance = $redis;
        } catch (Exception $ex) {
            throw new \Exception('Redis error - ' . $ex->getMessage());
        }
    }

    public function configInfo()
    {

        $ConfigModel = M('Config');
        $total_redpack_config = $ConfigModel->where(['varname' => 'cfg_total_redpack'])->find();
        if (!$total_redpack_config) {
            $this->assign('total_redpack_amount', '未定义');
        } else {
            $this->assign('total_redpack_amount', $total_redpack_config['value']);
        }

        $redpack_key = self::shuqian_key;

        $redis = self::getRedisInstance();
        $redcount = $redis->lLen($redpack_key);
        $this->assign('redpack_count', $redcount);

        $values = $redis->lRange($redpack_key, 0, -1);
        if (is_array($values)) {
            $redpack_left_amount = array_sum($values);
        } else {
            $redpack_left_amount = 0;
        }
        $this->assign('redpack_left_amount', $redpack_left_amount);

        $this->display();
    }

    //更新配置信息
    public function distributeTotal()
    {

        $ConfigModel = M('Config');

        $total_redpack_config = $ConfigModel->where(['varname' => 'cfg_total_redpack'])->find();
        if (!$total_redpack_config || $total_redpack_config['value'] < 1) {
            $this->error('红包金额上限未定义');
        }
        $this->distributeAndRefreshRedis($total_redpack_config['value']);

        $this->success('红包上限金额已分配');
    }


    private function distributeAndRefreshRedis($total)
    {
        // 规则：88元2个，58元5个，18.8元10个，1-5元随机
        $more = $total - 88 * 2 - 58 * 5 - 18.8 * 10;
        $fixedValues = [];
        $randoms = [];
        if ($more > 1) {
            // 如果总金额扣除固定金额红包后，任大于1则先创建固定金额的红包，剩下的随机分配
            for ($i = 1; $i <= 2; $i++) {
                $fixedValues[] = 88;
            }
            for ($i = 1; $i <= 5; $i++) {
                $fixedValues[] = 58;
            }
            for ($i = 1; $i <= 10; $i++) {
                $fixedValues[] = 18.8;
            }
            $randoms = $this->distribute($more);
        } elseif ($total - 58 * 5 - 18.8 * 10 > 1) {
            // 创建固定金额 58和18.8的，剩下的随机
            for ($i = 1; $i <= 5; $i++) {
                $fixedValues[] = 58;
            }
            for ($i = 1; $i <= 10; $i++) {
                $fixedValues[] = 18.8;
            }
            $more = $total - 58 * 5 - 18.8 * 10;
            $randoms = $this->distribute($more);
        } elseif ($total - 18.8 * 10 > 1) {
            // 创建10个18.8的红包，剩下的随机
            for ($i = 1; $i <= 10; $i++) {
                $fixedValues[] = 18.8;
            }
            $more = $total - 18.8 * 10;
            $randoms = $this->distribute($more);
        } elseif ($total > 1) {
            // 直接创建随机
            $randoms = $this->distribute($total);
        }
        $result = array_merge($fixedValues, $randoms);
        shuffle($result);

        $redis = self::getRedisInstance();
        // 定义红包列表key=shuqian_redpack_list
        $key = self::shuqian_key;
        $redis->del($key);//先删除key，再重装当前的红包
        array_unshift($result, $key);
        call_user_func_array([$redis, 'rPush'], $result);
        return true;
    }

    private function distribute($amount)
    {
        $redpack = [];
        while ($amount > 0) {
            if ($amount > 5) {
                $getVal = $this->randomFloat(1, 5);
            } elseif ($amount > 2) {
                $getVal = $this->randomFloat(1, $amount);
            } else {
                $getVal = $amount;
            }
            $leftAmount = $amount - $getVal;
            if ($leftAmount > 1 || $leftAmount == 0) {
                $redpack[] = (float)round($getVal, 2);
                $amount = $leftAmount;
            }
        }
        return $redpack;
    }

    private function randomFloat($min = 1, $max = 5)
    {
        $x = rand(0, 100);
        if ($x < 70) {
            $max = $max - ($max - $min) / 2;
        }
        $val = $min + mt_rand() / mt_getrandmax() * ($max - $min);
        return number_format($val, 2);
    }
}

?>
